D:\a\scloud-dns\scloud-dns\src\dns\resolver\mod.rs
Line | Count | Source |
1 | | pub(crate) mod stub; |
2 | | |
3 | | use crate::dns::packet::DNSPacket; |
4 | | use crate::dns::packet::additional::AdditionalSection; |
5 | | use crate::dns::packet::answer::AnswerSection; |
6 | | use crate::dns::packet::authority::AuthoritySection; |
7 | | use crate::dns::packet::question::QuestionSection; |
8 | | use crate::exceptions::SCloudException; |
9 | | |
10 | 3 | pub(crate) fn check_response_diff( |
11 | 3 | dns_packet: DNSPacket, |
12 | 3 | origin_questions: &[QuestionSection], |
13 | 3 | ) -> Result<(), SCloudException> { |
14 | 3 | let diff_answers = if !dns_packet.answers.is_empty() { |
15 | 2 | check_answer_diff(origin_questions, &dns_packet.answers) |
16 | | } else { |
17 | 1 | Ok(()) |
18 | | }; |
19 | | |
20 | 3 | let diff_authorities = if !dns_packet.authorities.is_empty() { |
21 | 1 | check_authority_diff(origin_questions, &dns_packet.authorities) |
22 | | } else { |
23 | 2 | Ok(()) |
24 | | }; |
25 | | |
26 | 3 | let diff_additionals = if !dns_packet.additionals.is_empty() { |
27 | 0 | check_additional_diff(origin_questions, &dns_packet.additionals) |
28 | | } else { |
29 | 3 | Ok(()) |
30 | | }; |
31 | | |
32 | 3 | if diff_answers.is_err() || diff_authorities2 .is_err2 () || diff_additionals2 .is_err2 () { |
33 | 1 | return Err(SCloudException::SCLOUD_RESOLVER_RESPONSE_MISMATCH); |
34 | 2 | } |
35 | | |
36 | 2 | Ok(()) |
37 | 3 | } |
38 | | |
39 | | /// Check that each question has at least one corresponding record |
40 | | /// in the answer, authority, or additional sections. |
41 | | /// |
42 | | /// This prevents responses that do not actually answer the query. |
43 | | /// |
44 | | /// # Exemple : |
45 | | /// ``` |
46 | | /// use crate::dns::resolver::check_answer_diff; |
47 | | /// use crate::dns::packet::question::QuestionSection; |
48 | | /// use crate::dns::packet::answer::AnswerSection; |
49 | | /// use crate::dns::q_type::DNSRecordType; |
50 | | /// use crate::dns::q_class::DNSClass; |
51 | | /// |
52 | | /// let questions = vec![QuestionSection { |
53 | | /// q_name: "example.com".to_string(), |
54 | | /// q_type: DNSRecordType::A, |
55 | | /// q_class: DNSClass::IN, |
56 | | /// }]; |
57 | | /// |
58 | | /// let answers = vec![AnswerSection { |
59 | | /// q_name: "example.com".to_string(), |
60 | | /// r_type: DNSRecordType::A, |
61 | | /// r_class: DNSClass::IN, |
62 | | /// ttl: 300, |
63 | | /// rdlength: 4, |
64 | | /// rdata: vec![93, 184, 216, 34], |
65 | | /// }]; |
66 | | /// |
67 | | /// assert!(check_answer_diff(&questions, &answers, &[], &[]).is_ok()); |
68 | | /// ``` |
69 | 4 | pub(crate) fn check_answer_diff( |
70 | 4 | questions: &[QuestionSection], |
71 | 4 | answers: &[AnswerSection], |
72 | 4 | ) -> Result<(), SCloudException> { |
73 | 4 | for record in answers.iter() { |
74 | 4 | if !questions.iter().any(|q| record.q_name == q.q_name) { |
75 | 2 | return Err(SCloudException::SCLOUD_RESOLVER_ANSWER_QNAME_MISMATCH); |
76 | 2 | } |
77 | | } |
78 | 2 | Ok(()) |
79 | 4 | } |
80 | | |
81 | | /// Ensure that authority records belong to the same zone |
82 | | /// as the original DNS questions. |
83 | | /// |
84 | | /// This prevents out-of-zone NS records. |
85 | | /// |
86 | | /// # Exemple : |
87 | | /// ``` |
88 | | /// use crate::dns::resolver::check_authority_diff; |
89 | | /// use crate::dns::packet::question::QuestionSection; |
90 | | /// use crate::dns::packet::authority::AuthoritySection; |
91 | | /// use crate::dns::q_type::DNSRecordType; |
92 | | /// use crate::dns::q_class::DNSClass; |
93 | | /// |
94 | | /// let questions = vec![QuestionSection { |
95 | | /// q_name: "example.com".to_string(), |
96 | | /// q_type: DNSRecordType::NS, |
97 | | /// q_class: DNSClass::IN, |
98 | | /// }]; |
99 | | /// |
100 | | /// let authorities = vec![AuthoritySection { |
101 | | /// q_name: "example.com".to_string(), |
102 | | /// q_type: DNSRecordType::NS, |
103 | | /// q_class: DNSClass::IN, |
104 | | /// ttl: 3600, |
105 | | /// ns_name: "ns1.example.com".to_string(), |
106 | | /// }]; |
107 | | /// |
108 | | /// assert!(check_authority_diff(&questions, &authorities).is_ok()); |
109 | | /// ``` |
110 | | #[allow(unused)] |
111 | 3 | pub(crate) fn check_authority_diff( |
112 | 3 | questions: &[QuestionSection], |
113 | 3 | authorities: &[AuthoritySection], |
114 | 3 | ) -> Result<(), SCloudException> { |
115 | 3 | for record in authorities.iter() { |
116 | 3 | if !questions.iter().any(|q| record.q_name == q.q_name) { |
117 | 1 | return Err(SCloudException::SCLOUD_RESOLVER_AUTHORITY_QNAME_MISMATCH); |
118 | 2 | } |
119 | | } |
120 | 2 | Ok(()) |
121 | 3 | } |
122 | | |
123 | | /// Ensure that additional records correspond to the original questions. |
124 | | /// |
125 | | /// This is commonly used to validate glue records. |
126 | | /// |
127 | | /// # Exemple : |
128 | | /// ``` |
129 | | /// use crate::dns::resolver::check_additional_diff; |
130 | | /// use crate::dns::packet::question::QuestionSection; |
131 | | /// use crate::dns::packet::additional::AdditionalSection; |
132 | | /// use crate::dns::q_type::DNSRecordType; |
133 | | /// use crate::dns::q_class::DNSClass; |
134 | | /// |
135 | | /// let questions = vec![QuestionSection { |
136 | | /// q_name: "example.com".to_string(), |
137 | | /// q_type: DNSRecordType::A, |
138 | | /// q_class: DNSClass::IN, |
139 | | /// }]; |
140 | | /// |
141 | | /// let additionals = vec![AdditionalSection { |
142 | | /// q_name: "example.com".to_string(), |
143 | | /// q_type: DNSRecordType::A, |
144 | | /// q_class: DNSClass::IN, |
145 | | /// ttl: 300, |
146 | | /// rdlength: 4, |
147 | | /// rdata: vec![192, 0, 2, 1], |
148 | | /// }]; |
149 | | /// |
150 | | /// assert!(check_additional_diff(&questions, &additionals).is_ok()); |
151 | | /// ``` |
152 | | #[allow(unused)] |
153 | 2 | pub(crate) fn check_additional_diff( |
154 | 2 | questions: &[QuestionSection], |
155 | 2 | additionals: &[AdditionalSection], |
156 | 2 | ) -> Result<(), SCloudException> { |
157 | 2 | for record in additionals.iter() { |
158 | 2 | if !questions.iter().any(|q| record.q_name == q.q_name) { |
159 | 1 | return Err(SCloudException::SCLOUD_RESOLVER_ADDITIONNAL_QNAME_MISMATCH); |
160 | 1 | } |
161 | | } |
162 | 1 | Ok(()) |
163 | 2 | } |